import {
  entityTableSelector,
  entityDetailsButtonSelector,
  entityDetailsBackButtonSelector,
<%_ if (!readOnly) { _%>
  entityCreateButtonSelector,
  entityCreateSaveButtonSelector,
  entityCreateCancelButtonSelector,
  <%_ if (updatableEntity) { _%>
  entityEditButtonSelector,
  <%_ } _%>
  entityDeleteButtonSelector,
  entityConfirmDeleteButtonSelector,
<%_ } _%>
} from '../../support/entity';
<%_

const baseApi = entityApi + 'api/';

const entityFakeData = generateFakeData('cypress');
const requiredRelationships = relationships.filter(rel => rel.relationshipRequired || rel.id);
const requiredOtherEntities = this._.uniq(requiredRelationships.map(rel => rel.otherEntity));
const otherEntities = this._.uniq(Object.values(differentRelationships).filter(rels => rels.length > 0).map(rels => rels[0].otherEntity));
// We cannot generate a required entity with relationship with required relationships.
const skipCreateTest =
  (
    !cypressBootstrapEntities ||
    requiredRelationships.some(rel => rel.otherEntity.primaryKey && rel.otherEntity.primaryKey.derived) ||
    requiredRelationships.some(rel => rel.otherEntity.builtInUser || rel.otherEntity === this.entity) ||
    requiredRelationships.map(rel => rel.otherEntity.relationships).flat().some(rel => rel.relationshipRequired) ||
    !entityFakeData
  ) ? '.skip' : '';

const sampleFields = fields.filter(f => !f.autoGenerate && !f.nullable);

if (workaroundEntityCannotBeEmpty && sampleFields.length === 0) {
  const sample = fields.find(f => !f.autoGenerate);
  if (sample) {
    sampleFields.push(sample);
  }
} else if (workaroundInstantReactiveMariaDB) {
  const samples = fields.filter(f => !f.autoGenerate && f.nullable && f.fieldType === 'Instant');
  if (samples.length > 0) {
    sampleFields.push(...samples);
  }
}
_%>

describe('<%- entityNameCapitalized %> e2e test', () => {

  const <%= entityInstance %>PageUrl = '/<%= entityPage %>';
  const <%= entityInstance %>PageUrlPattern = new RegExp('/<%= entityPage %>(\\?.*)?$');
  const username = Cypress.env('E2E_USERNAME') ?? '<%- adminEntity ? 'admin' : 'user' %>';
  const password = Cypress.env('E2E_PASSWORD') ?? '<%- adminEntity ? 'admin' : 'user' %>';
<%_ if (!readOnly) { _%>
  <% if (skipCreateTest) { %>// <% } %>const <%= entityInstance %>Sample = <%- JSON.stringify(this.generateTestEntity(sampleFields)) %>;
<%_ } _%>

  let <%= entityInstance %>;
<%_ for (otherEntity of requiredOtherEntities) { _%>
  <% if (skipCreateTest) { %>// <% } %>let <%= otherEntity.entityInstance %>;
<%_ } _%>

  beforeEach(() => {
    cy.login(username, password);
  });

<%_ if (requiredOtherEntities.length > 0) { _%>
  <%_ if (skipCreateTest) { _%>
  /* Disabled due to incompatibility
  <%_ } _%>
  beforeEach(() => {
  <%_ for (otherEntity of requiredOtherEntities) { _%>
    // create an instance at the required relationship entity:
    cy.authenticatedRequest({
      method: 'POST',
      url: '/<%= baseApi + otherEntity.entityApiUrl %>',
      body: <%- JSON.stringify(this.generateTestEntity(otherEntity.fields.filter(f => !f.autoGenerate))) %>,
    }).then(({ body }) => {
      <%= otherEntity.entityInstance %> = body;
    });
  <%_ } _%>
  });
  <%_ if (skipCreateTest) { _%>
   */
  <%_ } _%>

<%_ } _%>
  beforeEach(() => {
    cy.intercept('GET', '/<%= baseApi + entityApiUrl %>+(?*|)').as('entitiesRequest');
    cy.intercept('POST', '/<%= baseApi + entityApiUrl %>').as('postEntityRequest');
    cy.intercept('DELETE', '/<%= baseApi + entityApiUrl %>/*').as('deleteEntityRequest');
  });

<%_ if (requiredOtherEntities.length > 0) { _%>
  <%_ if (skipCreateTest) { _%>
  /* Disabled due to incompatibility
  <%_ } _%>
  beforeEach(() => {
    // Simulate relationships api for better performance and reproducibility.
  <%_ for (otherEntity of otherEntities) { _%>
    cy.intercept('GET', '/<%= baseApi + otherEntity.entityApiUrl %>', {
      statusCode: 200,
      body: [<%= requiredOtherEntities.includes(otherEntity) ? otherEntity.entityInstance : '' %>],
    });

  <%_ } _%>
  });
  <%_ if (skipCreateTest) { _%>
   */
  <%_ } _%>

<%_ } _%>
  afterEach(() => {
    if (<%= entityInstance %>) {
      cy.authenticatedRequest({
        method: 'DELETE',
        url: `/<%= baseApi + entityApiUrl %>/${<%= entityInstance %>.<%= primaryKey.name %>}`,
      }).then(() => {
        <%= entityInstance %> = undefined;
      });
    }
  });

<%_ if (requiredOtherEntities.length > 0) { _%>
  <%_ if (skipCreateTest) { _%>
  /* Disabled due to incompatibility
  <%_ } _%>
  afterEach(() => {
  <%_ for (otherEntity of requiredOtherEntities) { _%>
    if (<%= otherEntity.entityInstance %>) {
      cy.authenticatedRequest({
        method: 'DELETE',
        url: `/<%= baseApi + otherEntity.entityApiUrl %>/${<%= otherEntity.entityInstance %>.<%= otherEntity.primaryKey.name %>}`,
      }).then(() => {
        <%= otherEntity.entityInstance %> = undefined;
      });
    }
  <%_ } _%>
  });
  <%_ if (skipCreateTest) { _%>
   */
  <%_ } _%>

<%_ } _%>

  it('<%- entityNamePlural %> menu should load <%- entityNamePlural %> page', () => {
    cy.visit('/');
    cy.clickOnEntityMenuItem('<%= entityPage %>');
    cy.wait('@entitiesRequest').then(({ response }) => {
      if (response?.body.length === 0) {
        cy.get(entityTableSelector).should('not.exist');
      } else {
        cy.get(entityTableSelector).should('exist');
      }
    });;
    cy.getEntityHeading('<%- entityNameCapitalized %>').should('exist');
    cy.url().should('match', <%= entityInstance %>PageUrlPattern);
  });

  describe('<%- entityNameCapitalized %> page', () => {
<%_ if (!readOnly) { _%>
    describe('create button click', () => {
      beforeEach(() => {
        cy.visit(<%= entityInstance %>PageUrl);
        cy.wait('@entitiesRequest');
      });

      it('should load create <%- entityNameCapitalized %> page', () => {
        cy.get(entityCreateButtonSelector).click();
        cy.url().should('match', new RegExp('/<%= entityPage %>/new$'));
        cy.getEntityCreateUpdateHeading('<%- entityNameCapitalized %>');
        cy.get(entityCreateSaveButtonSelector).should('exist');
        cy.get(entityCreateCancelButtonSelector).click();
        cy.wait('@entitiesRequest').then(({ response }) => {
          expect(response?.statusCode).to.equal(200);
        });
        cy.url().should('match', <%= entityInstance %>PageUrlPattern);
      });
    });

<%_ } _%>
    describe('with existing value', () => {
<%_ if (!readOnly) { _%>
  <%_ if (skipCreateTest) { _%>
      /* Disabled due to incompatibility
  <%_ } _%>
      beforeEach(() => {
        cy.authenticatedRequest({
          method: 'POST',
          url: '/<%= baseApi + entityApiUrl %>',
  <%_ if (requiredRelationships.length > 0) { _%>
          body: {
            ...<%= entityInstance %>Sample,
    <%_ for (relationship of requiredRelationships) { _%>
            <%= relationship.propertyName %>: <%= relationship.collection ? '[' : '' %><%= relationship.otherEntity.entityInstance %><%= relationship.collection ? ']' : '' %>,
    <%_ } _%>
          },
  <%_ } else { _%>
          body: <%= entityInstance %>Sample,
  <%_ } _%>
        }).then(({ body }) => {
          <%= entityInstance %> = body;

          cy.intercept(
            {
              method: 'GET',
              url: '/<%= baseApi + entityApiUrl %>+(?*|)',
              times: 1,
            },
            {
              statusCode: 200,
  <%_ if (!paginationNo) { _%>
              headers: {
                link: '<http://localhost/<%= baseApi + entityApiUrl %>?page=0&size=20>; rel="last",<http://localhost/<%= baseApi + entityApiUrl %>?page=0&size=20>; rel="first"',
              },
  <%_ } _%>
              body: [<%= entityInstance %>],
            }
          ).as('entitiesRequestInternal');
        });

        cy.visit(<%= entityInstance %>PageUrl);

        cy.wait('@entitiesRequestInternal');
      });
  <%_ if (skipCreateTest) { _%>
       */

  <%_ } _%>
<%_ } _%>
<%_ if (readOnly || skipCreateTest) { _%>
      beforeEach(function () {
        cy.visit(<%= entityInstance %>PageUrl);

        cy.wait('@entitiesRequest').then(({ response }) => {
          if (response?.body.length === 0) {
            this.skip();
          }
        });
      });
<%_ } _%>

      it('detail button click should load details <%- entityNameCapitalized %> page', () => {
        cy.get(entityDetailsButtonSelector).first().click();
        cy.getEntityDetailsHeading('<%= entityInstance %>');
        cy.get(entityDetailsBackButtonSelector).click();
        cy.wait('@entitiesRequest').then(({ response }) => {
          expect(response?.statusCode).to.equal(200);
        });
        cy.url().should('match', <%= entityInstance %>PageUrlPattern);
      });

<%_ if (!readOnly && updatableEntity) { _%>
      it('edit button click should load edit <%- entityNameCapitalized %> page and go back', () => {
        cy.get(entityEditButtonSelector).first().click();
        cy.getEntityCreateUpdateHeading('<%- entityNameCapitalized %>');
        cy.get(entityCreateSaveButtonSelector).should('exist');
        cy.get(entityCreateCancelButtonSelector).click();
        cy.wait('@entitiesRequest').then(({ response }) => {
          expect(response?.statusCode).to.equal(200);
        });
        cy.url().should('match', <%= entityInstance %>PageUrlPattern);
      });

      <% if (jpaMetamodelFiltering && clientFrameworkVue && requiredRelationships.length) { %>// Reason: jpaMetamodelFiltering with required relationship missbehavior<% } %>
      it<% if (jpaMetamodelFiltering && clientFrameworkVue && requiredRelationships.length) { %>.skip<% } %>('edit button click should load edit <%- entityNameCapitalized %> page and save', () => {
        cy.get(entityEditButtonSelector).first().click();
        cy.getEntityCreateUpdateHeading('<%- entityNameCapitalized %>');
        cy.get(entityCreateSaveButtonSelector).click();
        cy.wait('@entitiesRequest').then(({ response }) => {
          expect(response?.statusCode).to.equal(200);
        });
        cy.url().should('match', <%= entityInstance %>PageUrlPattern);
      });

<%_ } _%>
<%_ if (!readOnly) { _%>
      <% if (skipCreateTest) { %>// Reason: cannot create a required entity with relationship with required relationships.<% } %>
      it<%= skipCreateTest %>('last delete button click should delete instance of <%- entityNameCapitalized %>', () => {
  <%_ if (clientFrameworkReact) { _%>
        cy.intercept('GET', '/<%= baseApi + entityApiUrl %>/*').as('dialogDeleteRequest');
  <%_ } _%>
        cy.get(entityDeleteButtonSelector).last().click();
  <%_ if (clientFrameworkReact) { _%>
        cy.wait('@dialogDeleteRequest');
  <%_ } _%>
        cy.getEntityDeleteDialogHeading('<%= entityInstance %>').should('exist');
        cy.get(entityConfirmDeleteButtonSelector).click();
        cy.wait('@deleteEntityRequest').then(({ response }) => {
          expect(response?.statusCode).to.equal(204);
        });
        cy.wait('@entitiesRequest').then(({ response }) => {
          expect(response?.statusCode).to.equal(200);
        });
        cy.url().should('match', <%= entityInstance %>PageUrlPattern);
  <% if (cypressBootstrapEntities) { %>
        <%= entityInstance %> = undefined;
  <%_ } _%>
      });
<%_ } _%>
    });
  });
<%_ if (!readOnly) { _%>

  describe('new <%- entityNameCapitalized %> page', () => {
    beforeEach(() => {
      cy.visit(<%= entityInstance %>PageUrl);
      cy.get(entityCreateButtonSelector).click();
      cy.getEntityCreateUpdateHeading('<%- entityNameCapitalized %>');
    });

    <% if (skipCreateTest) { %>// Reason: cannot create a required entity with relationship with required relationships.<% } %>
    it<%= skipCreateTest %>('should create an instance of <%- entityNameCapitalized %>', () => {
  <%_ fields.filter(field => (!field.id || !field.autoGenerate) && !field.hidden && !field.readonly).forEach((field) => {
    const fieldName = field.fieldName;
    const fieldIsEnum = field.fieldIsEnum;
    let fieldValue = !entityFakeData ? field.generateFakeData('cypress') : entityFakeData[field.fieldName];
    if (fieldValue === undefined) {
        return;
    }
    fieldValue = typeof fieldValue === 'string' ? fieldValue.replaceAll("'", "\\'") : fieldValue;
  _%>

    <%_ if (field.fieldTypeBoolean) { _%>
      cy.get(`[data-cy="<%= fieldName %>"]`).should('not.be.checked');
      cy.get(`[data-cy="<%= fieldName %>"]`).click();
      cy.get(`[data-cy="<%= fieldName %>"]`).should('be.checked');

    <%_ } else if (field.fieldTypeBinary && !field.blobContentTypeText) { _%>
      cy.setFieldImageAsBytesOfEntity('<%= fieldName %>', 'integration-test.png', 'image/png');

    <%_ } else if (fieldIsEnum) { _%>
      cy.get(`[data-cy="<%= fieldName %>"]`).select('<%- fieldValue %>');

    <%_ } else if (field.fieldTypeString || field.fieldTypeNumeric || field.fieldTypeLocalDate || field.fieldTypeTimed || field.fieldTypeDuration) { _%>
      cy.get(`[data-cy="<%= fieldName %>"]`).type('<%- fieldValue %>');
      <% if (field.fieldTypeLocalDate || field.fieldTypeTimed || field.fieldTypeDuration) { %>cy.get(`[data-cy="<%= fieldName %>"]`).blur();<% } %> cy.get(`[data-cy="<%= fieldName %>"]`).should('have.value', '<%- fieldValue %>');

    <%_ } else { _%>
      cy.get(`[data-cy="<%= fieldName %>"]`).type('<%- fieldValue %>');
      cy.get(`[data-cy="<%= fieldName %>"]`).invoke('val').should('match', new RegExp('<%- fieldValue %>'));

    <%_ } _%>
  <%_ }); _%>
  <%_ for (relationship of requiredRelationships) {
  _%>
       cy.get(`[data-cy="<%= relationship.relationshipFieldName %>"]`).select(<%= relationship.collection ? '[0]' : '1' %>);
  <%_ } _%>

  <%_ if (anyFieldHasFileBasedContentType) { _%>
      // since cypress clicks submit too fast before the blob fields are validated
      cy.wait(200); // eslint-disable-line cypress/no-unnecessary-waiting
  <%_ } _%>
      cy.get(entityCreateSaveButtonSelector).click();

      cy.wait('@postEntityRequest').then(({ response }) => {
        expect(response?.statusCode).to.equal(201);
        <%= entityInstance %> = response.body;
      });
      cy.wait('@entitiesRequest').then(({ response }) => {
        expect(response?.statusCode).to.equal(200);
      });
      cy.url().should('match', <%= entityInstance %>PageUrlPattern);
    });
  });
<%_ } _%>
});
